package cn.com.agree.pdfutilserver.util;

import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.text.PDFTextStripperByArea;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class PdfUtils {

    public static boolean savePageToPdf(String inpages,String filepath,int dpi,String outFilePath,String imgType){
        boolean result = false;
        PDDocument document = null;
        try {
            if(inpages.contains(",")){
                document = PDDocument.load(new File(filepath));
                PDFRenderer renderer = new PDFRenderer(document);
                String [] pageArr = inpages.split(",");
                String [] pathArr = FileUtils.getFileNameFromPath(outFilePath);

                for (int i = 0; i < pageArr.length; i++) {
                    String page = pageArr[i];
                    BufferedImage image =  renderer.renderImageWithDPI(Integer.parseInt(page), dpi); // 第一页，300 DPI

                    // 设置最大允许宽高
                    double maxWidth = width_in_pixels * dpi;
                    double maxHeight = height_in_pixels * dpi;

                    // 计算等比例缩放后的宽高
                    int originalWidth = image.getWidth();
                    int originalHeight = image.getHeight();
                    double ratio = Math.min(
                            maxWidth / (double) originalWidth,
                            maxHeight / (double) originalHeight
                    );
                    int targetWidth = (int) (originalWidth * ratio);
                    int targetHeight = (int) (originalHeight * ratio);

                    // 调整图片尺寸
                    BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
                    Graphics2D g = resizedImage.createGraphics();
                    g.drawImage(image, 0, 0, targetWidth, targetHeight, null);
                    g.dispose();

                    ImageIO.write(image, imgType, new File(pathArr[0]+File.separator+"i"+pathArr[1]));
                }
                document.close();
            }else{
                document = PDDocument.load(new File(filepath));
                PDFRenderer renderer = new PDFRenderer(document);
                BufferedImage image =  renderer.renderImageWithDPI(Integer.parseInt(inpages), dpi); // 第一页，300 DPI
                ImageIO.write(image, imgType, new File(outFilePath));
                document.close();
            }
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(document == null ){
                try {
                    document.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

    // A4纸宽度英尺
    public static double width_in_pixels = 8.27; // width_in_inches * DPI 可以得到像素的宽
    // A4纸高度英尺
    public static double height_in_pixels = 11.69; // height_in_inches * DPI 可以得到像素的高


    private static void replacePlaceholders(PDDocument document, Map<String, String> replacements) throws IOException {
        for (PDPage page : document.getDocumentCatalog().getPages()) {
            // 获取页面内容
            PDFTextStripperByArea stripper = new PDFTextStripperByArea();
            stripper.setSortByPosition(true);

            // 将 PDRectangle 转换为 Rectangle2D
            PDRectangle mediaBox = page.getMediaBox();
            Rectangle2D region = new Rectangle2D.Float(
                    mediaBox.getLowerLeftX(),
                    mediaBox.getLowerLeftY(),
                    mediaBox.getWidth(),
                    mediaBox.getHeight()
            );

            stripper.addRegion("content", region);
            stripper.extractRegions(page);

            String pageText = stripper.getTextForRegion("content");

            // 替换占位符
            for (Map.Entry<String, String> entry : replacements.entrySet()) {
                pageText = pageText.replace(entry.getKey(), entry.getValue());
            }

            // 清空页面内容
            PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.OVERWRITE, true);
            contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);
            contentStream.beginText();
            contentStream.newLineAtOffset(50, 700); // 设置文本起始位置
            contentStream.showText(pageText); // 写入替换后的文本
            contentStream.endText();
            contentStream.close();
        }
    }


    // 字体配置（假设字体文件存放在 resources/fonts 目录）
    private static final String FONT_FAMILY = "ZhichunSong"; // 统一字体家族名
    private static final Map<String, String> FONT_MAPPING;
    static {
        Map<String, String> fontMap = new HashMap<>();
        fontMap.put("simhei", "fonts/SIMHEI.TTF");
        fontMap.put("simsun",    "fonts/simsun.ttf");
        fontMap.put("zhichunsong",  "fonts/zhichunsong.ttf");
        fontMap.put("zhichunsongP2",  "fonts/zhichunsongp2.ttf");
        fontMap.put("zhichunsongP3",  "fonts/zhichunsongp3.ttf");
        FONT_MAPPING = Collections.unmodifiableMap(fontMap);
    }

    /**
     * 将 HTML 文件转换为 PDF（自动加载志春宋体）
     * @param htmlPath  HTML 文件路径（如 /data/input.html）
     * @param pdfPath   输出 PDF 路径（如 /data/output.pdf）
     */
    public static void htmlToPdf(String htmlPath, String pdfPath) {
        // 1. 确保输出目录存在
        createParentDirs(pdfPath);

        try (OutputStream os = Files.newOutputStream(Paths.get(pdfPath))) {
            // 2. 读取 HTML 内容
            String htmlContent = readHtmlFile(htmlPath);

            // 3. 构建 PDF 渲染器
            PdfRendererBuilder builder = new PdfRendererBuilder();
            loadFonts(builder);  // 加载字体
            builder.withHtmlContent(htmlContent, getBaseUri(htmlPath)); // 设置基准路径
            builder.toStream(os);
            builder.run();

        } catch (Exception e) {
            throw new RuntimeException("HTML 转 PDF 失败: " + e.getMessage(), e);
        }
    }

    //-- 以下为工具方法 --//

    /**
     * 读取 HTML 文件内容
     */
    private static String readHtmlFile(String htmlPath) throws IOException {
        return new String(Files.readAllBytes(Paths.get(htmlPath)));
    }


    private static void loadFonts(PdfRendererBuilder builder) throws IOException {
        for (Map.Entry<String, String> entry : FONT_MAPPING.entrySet()) {
            String style = entry.getKey();
            String fontPath = entry.getValue();

            File fontFile = getFontFile(fontPath);
            builder.useFont(fontFile,style);
        }
    }

    /**
     * 加载字体文件（支持 JAR 内资源）
     */
    private static File getFontFile(String fontPath) throws IOException {
        InputStream is = PdfUtils.class.getClassLoader().getResourceAsStream(fontPath);
        if (is == null) {
            throw new FileNotFoundException("字体文件未找到: " + fontPath);
        }

        // 创建临时字体文件（OpenHTMLToPDF 需要文件路径）
        String suffix = fontPath.substring(fontPath.lastIndexOf("."));
        File tempFont = File.createTempFile("font_", suffix);
        Files.copy(is, tempFont.toPath(), StandardCopyOption.REPLACE_EXISTING);
        return tempFont;
    }


    /**
     * 生成基准 URI（解决相对路径问题）
     */
    private static String getBaseUri(String htmlPath) {
        return "file://" + Paths.get(htmlPath).getParent().toAbsolutePath() + "/";
    }

    /**
     * 创建输出文件的父目录
     */
    private static void createParentDirs(String filePath) {
        File file = new File(filePath);
        File parentDir = file.getParentFile();
        if (parentDir != null && !parentDir.exists()) {
            parentDir.mkdirs();
        }
    }
}
